package com.example.guarding_jc;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.charset.Charset;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.nfc.tech.IsoDep;
import android.text.format.DateFormat;
import android.util.Log;

public class Utility {
	
	//format: [len_mac] [len_seq] [len_challenge] [len_uid] [len_imei] [len_time] [mac] [seq] [challenge] [uid] [imei] [time]
	/*
	 * extract MAC from the response from tag
	 */
	public static byte[] extractMac(byte[] response){
		int szMac = (int) response[0];
		byte[] Mac = new byte[szMac];
		System.arraycopy(response, 6, Mac, 0, szMac);
		return Mac;
	}
	
	/*
	 * Extract sequence number
	 */
	public static byte[] extractSequence(byte[] response){
		int szMac = (int) response[0];
		int szSequence = (int) response[1];
		byte[] sequence = new byte[szSequence];
		System.arraycopy(response, 6 + szMac, sequence, 0, szSequence);
		return sequence;
	}
	
	/*
	 * Extract challenge
	 */
	public static byte[] extractChallenge(byte[] response){
		int szMac = (int) response[0];
		int szSequence = (int) response[1];
		int szChallenge = (int) response[2];
		
		byte[] challenge;
		
		if (szChallenge > 0){
			challenge = new byte[szChallenge];
			System.arraycopy(response, 6 + szMac + szSequence, challenge, 0, szChallenge);
		}
		else{
			challenge = new byte[1];
			challenge[0] = (byte)0x00;
		}
		return challenge;
	}
	
	public static byte[] extractUID(byte[] response){
		int szMac = (int) response[0];
		int szSequence = (int) response[1];
		int szChallenge = (int) response[2];
		int szUid = (int) response[3];
		byte[] uid = new byte[szUid];
		System.arraycopy(response, 6 + szMac + szSequence + szChallenge, uid, 0, szUid);
		return uid;
	}
	
	public static byte[] extractIMEI(byte[] response){
		int szMac = (int) response[0];
		int szSequence = (int) response[1];
		int szChallenge = (int) response[2];
		int szUid = (int) response[3];
		int szIMEI = (int) response[4];
		byte[] imei = new byte[szIMEI];
		System.arraycopy(response, 6 + szMac + szSequence + szChallenge + szUid, imei, 0, szIMEI);
		return imei;
	}
	
	public static byte[] extractTime(byte[] response){
		int szMac = (int) response[0];
		int szSequence = (int) response[1];
		int szChallenge = (int) response[2];
		int szUid = (int) response[3];
		int szIMEI = (int) response[4];
		int szTime = (int) response[5];
		byte[] time = new byte[szTime];
		
		System.arraycopy(response, 6 + szMac + szSequence + szChallenge + szUid + szIMEI, time, 0, szTime);
		return time;
	}
	/*
	 * Function to insert an entry to the db
	 */
	public static void insertIntoDB(String tag_uid, TosendDataSource datasource, byte[] response){
		byte[] Mac = extractMac(response);
		byte[] sequence = extractSequence(response);
		byte[] challenge = extractChallenge(response);
		byte[] time = extractTime(response);
		byte[] imei = extractIMEI(response);
		datasource.createEntry(toHexString(sequence), toHexString(challenge), toHexString(Mac),
								tag_uid, toHexString(time), toHexString(imei));
	}
	
	/*
	 * Delete an entry
	 */
	
	public static void deleteEntry(TosendDataSource datasource, String entryId){
		datasource.deleteEntry(entryId);
	}
	
	
	/*
	 * Send request to a tag (without challenge) when we do not have Internet connection
	 */
	
	public static byte[] sendToTag(IsoDep nfc, byte[] cmdApdu){
		try{
			//byte[] cmdApdu = cmd.toByteArray();
			//Log.i("cmdApdu: ", Utility.toHexString(cmdApdu));
			Log.i("Before sending cmd to tag", "hehe");
			byte[] response = nfc.transceive(cmdApdu);
			Log.i("Send response to tag", toHexString(response));
			return response;
		}
		catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	/*
	 * Send request to server and get resonse
	 */
	public static String sendToServer(String requestedURL){
		String returnedStr = "";
		Log.i("requested_url", requestedURL);
		HttpGet request = new HttpGet(requestedURL);
		
		request.setHeader("Accept", "text/plain");
		request.setHeader("Content-type", "text/plain");
		
		DefaultHttpClient httpclient = new DefaultHttpClient();
		try{
			HttpResponse response = httpclient.execute(request);
			HttpEntity responseEntity = response.getEntity();
			String value = EntityUtils.toString(responseEntity);
			returnedStr = value;
			Log.i("Value of returned Str = ", returnedStr);
			return returnedStr;
		}
		catch(Exception e){
			e.printStackTrace();
			return "";
		}
	}
	
	/*
	 * convert bytes to a string of hex
	 */
	public static String toHexString(byte[] b) {
	    StringBuffer sb = new StringBuffer();
	    for (int i = 0; i < b.length; i++){
	    	sb.append(Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1));
	    }
	    return sb.toString();
	}
	
	/*
	 * convert a string of hex to bytes
	 */
	public static byte[] toByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	/*
	 * Get the current time
	 */
	public static String getCurrentTime(){
		//get current time
		DateFormat df = new DateFormat();
		String time = df.format("yyyy-MM-dd hh:mm:ss", new java.util.Date()).toString();
		return time;
	}
	
	/*
	 * A function to convert an array of bytes to a string of ascii characters
	 */
	
	
	/*
	 * check if the server is available or not
	 */
	
	public static boolean isServerAvailable(String ip, int port){
		try{
			boolean exists = false;
			SocketAddress sockAddr = new InetSocketAddress(ip, port);
			Socket sock = new Socket();
			int timeOut = 2000; //ms
			sock.connect(sockAddr, timeOut);
			exists = true;
			sock.close();
			return exists;
		}
		catch(IOException ioe){
			ioe.printStackTrace();
			return false;
		}
	}
}
